#ifndef _UDP_CLIENT_HPP
#define _UDP_CLIENT_HPP

#include <arpa/inet.h>
#include <fcntl.h>
#include <ifaddrs.h>
#include <linux/can.h>
#include <linux/can/raw.h>
#include <net/if.h>
#include <netinet/in.h>
#include <poll.h>
#include <pthread.h>
#include <sched.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

#include <iostream>
#include <opencv2/opencv.hpp>
#include <queue>

#include "common.h"

using namespace cv;
using namespace std;

#define SERVER_PORT 2022

#define READ_BUFF_LEN 1024
#define FLAG_BUFF_LEN 1

#define HEAD_MARK 0xabcd0001

#define UDP_SEND_SRC 'a'
#define UDP_SEND_DET 'b'
#define UDP_SEND_DETLIST 'c'
#define UDP_SEND_LEFTLIST 'd'
#define UDP_SEND_RIGHTLIST 'e'

#define SEND_SRC 0x1
#define SEND_DET 0x2
#define SEND_DETLIST 0x4
#define SEND_SEG 0x8

struct SUdpDataHead {
  int mHeadMark;
  int mSendMask;
  int mRcvMask;
  int mIndex;
};

struct SUdpFileData {
  int mIndex;
  string mFileMsg;
};

struct SUdpData {
  Mat src;
  SUdpDataHead udp_head;
};

class UdpClient {
 public:
  UdpClient();
  ~UdpClient();
  void SetAddr(const char *addr, int port);
  void UdpMatSender(SUdpData udp_data);

 private:
  int mClientFd;
  struct sockaddr_in mSerAddr;
  struct sockaddr *mUdpDst;
  socklen_t mUdpDstLen;
  char *mBuf;  // 缓冲区指针
  char *mBufFlag;
};

UdpClient::UdpClient() {
  mClientFd = socket(AF_INET, SOCK_DGRAM, 0);
  if (mClientFd < 0) {
    printf("create socket fail!\n");
  }
}

void UdpClient::SetAddr(const char *addr, int port) {
  memset(&mSerAddr, 0, sizeof(mSerAddr));
  mSerAddr.sin_family = AF_INET;
  mSerAddr.sin_addr.s_addr = inet_addr(addr);
  mSerAddr.sin_port = htons(port);  // 注意网络序转换

  mUdpDst = (struct sockaddr *)&mSerAddr;
  mUdpDstLen = sizeof(*mUdpDst);
}

UdpClient::~UdpClient() { close(mClientFd); }

void UdpClient::UdpMatSender(SUdpData udp_data) {
  std::vector<uchar> data_encode;
  std::vector<int> quality;
  quality.push_back(IMWRITE_JPEG_QUALITY);
  quality.push_back(50);                                 // 进行50%的压缩
  imencode(".jpg", udp_data.src, data_encode, quality);  // 将图像编码
  uchar encode_array[data_encode.size()];
  memcpy(encode_array, &data_encode[0], data_encode.size() * sizeof(uchar));

  sendto(mClientFd, encode_array, data_encode.size(), 0, mUdpDst, mUdpDstLen);
}

#endif
